// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.core.launch;

import static org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants.CONSOLE_OPEN_ON_ERR;
import static org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants.CONSOLE_OPEN_ON_OUT;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.dengues.commons.connectivity.IConnectivitySettingsConstants;
import org.dengues.commons.utils.FileUtils;
import org.dengues.core.DenguesCorePlugin;
import org.dengues.core.ExceptionOperation;
import org.dengues.core.codegen.ICodeGenerator;
import org.dengues.core.components.IXMLComponent;
import org.dengues.core.export.EtlProcessScriptsManager;
import org.dengues.core.module.EClasspathVariables;
import org.dengues.core.process.ICompProcess;
import org.dengues.core.resource.DenguesProjectFactory;
import org.dengues.core.resource.WarehouseResourceFactory;
import org.dengues.core.runprocess.IJavaETLProcessor;
import org.dengues.core.runprocess.JavaProcessorUtil;
import org.dengues.core.warehouse.ENodeCategoryName;
import org.dengues.designer.core.codegen.ProcessCodeGenerator;
import org.dengues.designer.core.components.ComponentsFactory;
import org.dengues.model.warehouse.ScriptsStorage;
import org.dengues.ui.prefs.connectivity.XMLFileManager;
import org.dengues.ui.prefs.connectivity.models.ConnectivityProperty;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.emf.codegen.util.CodeGenUtil;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 1 2006-09-29 17:06:40Z qiang.zhang $
 * 
 */
public class JavaETLProcessor implements IJavaETLProcessor {

    private static Logger log = Logger.getLogger(JavaETLProcessor.class);

    protected static IJavaProject javaProject;

    protected static IProject project;

    protected IPath codePath;

    protected IPath compiledCodePath;

    private ICompProcess process;

    private IFile codeFile;

    private IPath path;

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaETLProcessor#getJavaProject()
     */
    public IJavaProject getJavaProject() {
        if (javaProject == null) {
            initJavaProject();
        }
        return javaProject;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com JavaETLProcessor constructor comment.
     */
    public JavaETLProcessor() {
        super();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com JavaETLProcessor constructor comment.
     * 
     * @param process
     * @param path
     */
    public JavaETLProcessor(ICompProcess process, IPath path) {
        this();
        this.process = process;
        this.path = path;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaETLProcessor#initJavaProject()
     */
    public void initJavaProject() {
        if (javaProject != null) {
            return;
        }
        try {
            initProject();
            javaProject = JavaCore.create(project);
            IClasspathEntry classpathEntry = JavaCore.newSourceEntry(new Path("/" + project.getName() + "/" //$NON-NLS-1$ //$NON-NLS-2$
                    + JavaProcessorUtil.JAVA_PROJ_SRC));
            IClasspathEntry jreClasspathEntry = JavaCore.newContainerEntry(new Path("org.eclipse.jdt.launching.JRE_CONTAINER")); //$NON-NLS-1$
            List<IClasspathEntry> classpath = new ArrayList<IClasspathEntry>();
            classpath.add(classpathEntry);
            classpath.add(jreClasspathEntry);

            classpath.addAll(addDriverClasses());
            // classpath.addAll(addVariable(javaProject, "DENGUES_LIB", Activator.PLUGIN_ID)); //$NON-NLS-1$
            // add the classpath variables
            for (EClasspathVariables var : EClasspathVariables.values()) {
                IClasspathEntry hsqlClasspathEntry = JavaCore.newVariableEntry(new Path(var.toString()), null, null); //$NON-NLS-1$
                classpath.add(hsqlClasspathEntry);
            }
            IFolder sourceFolder = project.getFolder(new Path(JavaProcessorUtil.JAVA_PROJ_SRC));
            if (!sourceFolder.exists()) {
                sourceFolder.create(false, true, null);
            }
            IFolder runtimeFolder = project.getFolder(new Path(JavaProcessorUtil.JAVA_PROJ_CLASSES));
            if (!runtimeFolder.exists()) {
                runtimeFolder.create(false, true, null);
            }
            javaProject.setRawClasspath(classpath.toArray(new IClasspathEntry[0]), null);
            javaProject.setOutputLocation(new Path("/" + project.getName() + "/" + JavaProcessorUtil.JAVA_PROJ_CLASSES), null); //$NON-NLS-1$ //$NON-NLS-2$
            // javaProject.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, "1.6"); //$NON-NLS-1$ //$NON-NLS-2$
            getInternalPackage();
        } catch (Exception e) {
            log.error("initJavaProject Exception: ", e); //$NON-NLS-1$
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addDriverClasses".
     * 
     * @return
     */
    private List<IClasspathEntry> addDriverClasses() {
        List<IClasspathEntry> list = new ArrayList<IClasspathEntry>();
        try {
            List<String> existPaths = new ArrayList<String>();
            ConnectivityProperty[] loadPropertySets = XMLFileManager.loadPropertySets();
            for (ConnectivityProperty property : loadPropertySets) {
                String jarList = (String) property.getBaseProperties().get(IConnectivitySettingsConstants.PROP_DEFN_JARLIST);
                String[] jars = XMLFileManager.parseString(jarList);
                for (String string : jars) {
                    if (!existPaths.contains(string)) {
                        existPaths.add(string);
                        File file = new File(string);
                        if (string.toLowerCase().endsWith(".dll")) { //$NON-NLS-1$
                            String libpath = System.getProperty("java.library.path"); //$NON-NLS-1$
                            String sep = System.getProperty("path.separator"); //$NON-NLS-1$
                            String parentPath = file.getParentFile().getAbsolutePath();
                            String[] split = libpath.split(sep);
                            boolean b = Arrays.asList(split).contains(parentPath);
                            if (!b) {
                                libpath = libpath + sep + parentPath;
                                System.setProperty("java.library.path", libpath); //$NON-NLS-1$
                            }
                        } else {
                            if (file.exists() && file.isFile()) {
                                list.add(JavaCore.newLibraryEntry(new Path(string), null, null));
                            }
                        }
                    }
                }
            }
        } catch (CoreException ex) {
            ex.printStackTrace();
        }

        return list;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "synDenguesApi".
     */
    public void synDenguesApi() {
        if (project == null) {
            initProject();
        }
        try {
            File prjFile = project.getLocation().toFile();
            File srcFile = new File(prjFile, JavaProcessorUtil.JAVA_PROJ_SRC);
            prjFile = new File(srcFile, JavaProcessorUtil.JAVA_DENGUES_PKG);
            srcFile = new File(prjFile, JavaProcessorUtil.DENGUESAPI_PKG);
            File denDir = getDenguesApiPkg();
            IPackageFragment sysPkg = getDenguesApi(JavaProcessorUtil.DENGUESAPI_PKG);
            if (denDir != null && denDir.isDirectory()) {
                File sysDir = denDir.listFiles(new FilenameFilter() {

                    public boolean accept(File dir, String name) {
                        return name.equals(JavaProcessorUtil.DENGUESAPI_PKG);
                    }
                })[0];
                if (sysDir.isDirectory()) {
                    File[] apiFiles = sysDir.listFiles(new FilenameFilter() {

                        public boolean accept(File dir, String name) {
                            return name.endsWith(".java"); //$NON-NLS-1$
                        }
                    });
                    for (File file : apiFiles) {
                        FileUtils.copy(file, new File(srcFile, file.getName()));
                    }
                }
            }
            sysPkg.getResource().refreshLocal(IResource.DEPTH_ONE, null);

            addImportLibraries();
            IPackageFragment cusPkg = getDenguesApi(JavaProcessorUtil.CUSTOMERAPI_PKG);
            File destDir = new File(prjFile, JavaProcessorUtil.CUSTOMERAPI_PKG);
            List<Object> allScript = WarehouseResourceFactory.getAllObjectsFromEMF(ENodeCategoryName.SCRIPTS);
            for (Object object : allScript) {
                ScriptsStorage storage = (ScriptsStorage) object;
                String content = storage.getContent();
                if (content != null && content.length() > 0) {
                    File file = new File(destDir, storage.getName() + JavaProcessorUtil.JAVA_EXTENSION);
                    FileWriter writer = new FileWriter(file);
                    writer.write(content);
                    writer.flush();
                    writer.close();
                }
            }
            cusPkg.getResource().refreshLocal(IResource.DEPTH_ONE, null);

        } catch (Exception e) {
            log.error("Get Dengues Api Location is Error: ", e); //$NON-NLS-1$
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getDenguesApi".
     * 
     * @return
     * @throws Exception
     */
    private IPackageFragment getDenguesApi(String pkg) throws Exception {
        IPackageFragment sysPkg = getProjectPackage(getProjectPackage(JavaProcessorUtil.JAVA_DENGUES_PKG), pkg);
        return sysPkg;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getDenguesApiPkg".
     * 
     * @throws IOException
     */
    public static File getDenguesApiPkg() throws IOException {
        URL url = null;
        Bundle bundle = DenguesCorePlugin.getDefault().getBundle();
        URL componentURL = FileLocator.find(bundle, new Path(JavaProcessorUtil.DENGUESAPI), null);
        url = FileLocator.toFileURL(componentURL);
        File dir = new File(url.getPath());
        if (dir.isDirectory()) {
            File denDir = dir.listFiles(new FilenameFilter() {

                public boolean accept(File dir, String name) {
                    return name.equals(JavaProcessorUtil.JAVA_DENGUES_PKG);
                }
            })[0];
            return denDir;
        }
        return null;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addImportLibraries".
     */
    private void addImportLibraries() {
        IPath customModulePath = DenguesCorePlugin.getCustomModulePath();
        File cusModDir = new File(customModulePath.toPortableString());
        if (cusModDir.isDirectory()) {
            IJavaProject javaProject = getJavaProject();
            try {
                File[] listFiles = cusModDir.listFiles();
                IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
                int length = rawClasspath.length;
                IClasspathEntry[] newClasspath = new IClasspathEntry[length + listFiles.length];
                System.arraycopy(rawClasspath, 0, newClasspath, 0, length);
                for (int i = 0; i < listFiles.length; i++) {
                    File jfile = listFiles[i];
                    newClasspath[length + i] = JavaCore.newLibraryEntry(new Path(jfile.getAbsolutePath()), null, null);
                }
                javaProject.setRawClasspath(newClasspath, null);
            } catch (Exception e) {
                ExceptionOperation.operate(e);
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "initProject".
     */
    private static void initProject() {
        try {
            IWorkspace workspace = ResourcesPlugin.getWorkspace();
            IWorkspaceRoot root = workspace.getRoot();
            project = root.getProject(JavaProcessorUtil.JAVA_PROJ_NAME);
            if (!project.exists()) {
                project.create(null);
                IProjectDescription description = workspace.newProjectDescription(JavaProcessorUtil.JAVA_PROJ_NAME);
                description.setNatureIds(new String[] { JavaCore.NATURE_ID });
                description.setLocation(null);
                project.open(IResource.BACKGROUND_REFRESH, null);
                project.setDescription(description, null);
            } else {
                project.open(IResource.BACKGROUND_REFRESH, null);
                IProjectDescription description = project.getDescription();
                description.setNatureIds(new String[] { JavaCore.NATURE_ID });
                project.setDescription(description, null);
            }
        } catch (Exception e) {
            log.error("initProject Exception: ", e); //$NON-NLS-1$
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "initCodePath".
     */
    private void initCodePath() {
        try {
            String prjName = DenguesProjectFactory.getDenguesProject().getProject().getName();
            IPackageFragment processorPackage = getProjectPackage(JavaProcessorUtil.JAVA_DENGUES_PKG);
            IPackageFragment prjPackage = getProjectPackage(processorPackage, JavaProcessorUtil.JAVA_PROJ_CODE_PKG);
            prjPackage = getProjectPackage(prjPackage, prjName.toLowerCase().replaceAll(" ", ""));//$NON-NLS-1$ //$NON-NLS-2$
            prjPackage = getProjectPackage(prjPackage, path);
            this.codePath = prjPackage.getPath().append(process.getName() + JavaProcessorUtil.JAVA_EXTENSION);
            this.codePath = this.codePath.removeFirstSegments(1);
            this.compiledCodePath = this.codePath.removeLastSegments(1).append(process.getName());
            this.compiledCodePath = new Path(JavaProcessorUtil.JAVA_PROJ_CLASSES).append(this.compiledCodePath
                    .removeFirstSegments(1));
        } catch (Exception e) {
            log.error("initCodePath Exception: ", e); //$NON-NLS-1$
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getProjectPackage".
     * 
     * @param prjPackage
     * @param path2
     */
    public IPackageFragment getProjectPackage(IPackageFragment prjPackage, IPath path2) throws Exception {
        if (path2.segmentCount() == 0) {
            return prjPackage;
        } else if (path2.segmentCount() == 1) {
            return getProjectPackage(prjPackage, path2.segment(0));
        } else {
            IPackageFragment fragment = getProjectPackage(prjPackage, path2.segment(0));
            return getProjectPackage(fragment, path2.removeFirstSegments(1));
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getProjectPackage".
     * 
     * @param prjPackage
     * @param pName
     * @return
     * @throws Exception
     */
    private IPackageFragment getProjectPackage(IPackageFragment prjPackage, String pName) throws Exception {
        IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(prjPackage.getResource());
        IPackageFragment packageFragment = root.getPackageFragment(pName);
        if (!packageFragment.exists()) {
            root.createPackageFragment(pName, false, null);
        }
        return root.getPackageFragment(pName);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getProjectPackage".
     * 
     * @param projName
     * @return
     * @throws Exception
     */
    private IPackageFragment getProjectPackage(String projName) throws Exception {
        IPackageFragmentRoot root = getJavaProject().getPackageFragmentRoot(project.getFolder(JavaProcessorUtil.JAVA_PROJ_SRC));
        IPackageFragment packageFragment = root.getPackageFragment(projName);
        if (!packageFragment.exists()) {
            root.createPackageFragment(projName, false, null);
        }
        return root.getPackageFragment(projName);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaETLProcessor#generateCode()
     */
    public void generateCode(boolean statics) {
        try {
            initCodePath();
            List<IXMLComponent> components = new ComponentsFactory().getComponents();
            if (!components.isEmpty()) {
                ICodeGenerator codeGenerator = new ProcessCodeGenerator(process, path);
                String processCode = codeGenerator.generateProcessCode(statics);
                // Generating files
                codeFile = this.project.getFile(this.codePath);
                InputStream codeStream = new ByteArrayInputStream(processCode.getBytes());

                if (!codeFile.exists()) {
                    codeFile.create(codeStream, true, null);
                } else {
                    codeFile.setContents(codeStream, true, false, null);
                }
                javaProject.getResource().getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null);
            }
        } catch (Exception e) {
            log.error("generateCode Exception: ", e); //$NON-NLS-1$
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaETLProcessor#run(java.lang.String[])
     */
    public Process run(String[] libpath) {
        try {
            generateCode(true);
            synDenguesApi();
            String[] cmd = getCommandLine(libpath);
            logCommandLine(cmd);
            return Runtime.getRuntime().exec(cmd);
        } catch (Exception e) {
            log.error("run Process Exception: ", e); //$NON-NLS-1$
        }
        return null;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "logCommandLine".
     * 
     * @param cmd
     */
    private void logCommandLine(String[] cmd) {
        StringBuffer sb = new StringBuffer();
        sb.append("Command line: "); //$NON-NLS-1$
        for (String s : cmd) {
            sb.append(' ').append(s);
        }
        log.log(Level.INFO, sb);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getCommandLine".
     * 
     * @param libpath
     * @return
     */
    private String[] getCommandLine(String[] libpath) {
        String separator = System.getProperty("path.separator"); //$NON-NLS-1$
        return getCommandLine(libpath, separator);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getCommandLine".
     * 
     * @param libpath
     * @param separator
     * @return
     */
    private String[] getCommandLine(String[] libpath, String separator) {
        StringBuffer libPath = new StringBuffer();
        String command = "java"; //$NON-NLS-1$
        for (String string : libpath) {
            libPath.append(FileUtils.getOSPath(string) + separator);
        }
        // init project_path
        String projectPath;
        IFolder classesFolder = getJavaProject().getProject().getFolder(JavaProcessorUtil.JAVA_PROJ_CLASSES); //$NON-NLS-1$
        IPath projectFolderPath = classesFolder.getFullPath().removeFirstSegments(1);
        projectPath = Path.fromOSString(project.getLocation().toOSString()).append(projectFolderPath).toOSString();

        // init class name
        IPath classPath = getCompiledCodePath().removeFirstSegments(1);
        String className = classPath.toString().replace('/', '.');

        return new String[] { new Path(command).toPortableString(), "-Xms256M", "-Xmx1024M", "-cp", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                libPath.toString() + new Path(projectPath).toPortableString(), className };
    }

    /**
     * Getter for compiledCodePath.
     * 
     * @return the compiledCodePath
     */
    private IPath getCompiledCodePath() {
        if (compiledCodePath == null) {
            initCodePath();
        }
        return this.compiledCodePath;
    }

    /**
     * Getter for codeFile.
     * 
     * @return the codeFile
     */
    public IFile getCodeFile() {
        if (this.codeFile == null || !this.codeFile.exists()) {
            generateCode(true);
        }
        return this.codeFile;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaProcessor#launch()
     */
    public ILaunch launch(boolean isStat) throws CoreException {
        // init class name
        // generateCode(isStat);
        IPath classPath = getCompiledCodePath().removeFirstSegments(1);
        String className = classPath.toString().replace('/', '.');
        return DenguesProcessFactory.launch(getJavaProject(), DenguesProjectFactory.getDenguesProject().getName().toLowerCase()
                + classPath.lastSegment().toLowerCase() + " (" + getJavaProject().getElementName() + ")", className, //$NON-NLS-1$ //$NON-NLS-2$
                new String());
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addVariable".
     * 
     * @param javaProject
     * @param variableName
     * @param pluginID
     * @return
     */
    private List<IClasspathEntry> addVariable(IJavaProject javaProject, String variableName, String pluginID) {
        final List<IClasspathEntry> list = new ArrayList<IClasspathEntry>();
        Bundle bundle = Platform.getBundle(pluginID);
        URL classpathURL = bundle != null && Platform.inDevelopmentMode() ? bundle.getEntry(".classpath") : null; //$NON-NLS-1$

        // If it doesn't correspond to a bundle, then try to process it as a project in the workspace.
        //
        if (bundle == null) {
            try {
                IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(pluginID);
                if (project != null) {
                    classpathURL = new File(project.getLocation() + "/.classpath").toURL(); //$NON-NLS-1$
                }
            } catch (MalformedURLException exception) {
                exception.printStackTrace();
            }
        }
        if (classpathURL != null) {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            documentBuilderFactory.setNamespaceAware(true);
            documentBuilderFactory.setValidating(false);
            try {
                DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
                Document document = documentBuilder.parse(new InputSource(classpathURL.toString()));
                for (Node child = document.getDocumentElement().getFirstChild(); child != null; child = child.getNextSibling()) {
                    if (child.getNodeType() == Node.ELEMENT_NODE) {
                        Element classpathEntryElement = (Element) child;
                        if ("classpathentry".equals(classpathEntryElement.getNodeName()) //$NON-NLS-1$
                                && "output".equals(classpathEntryElement.getAttribute("kind"))) { //$NON-NLS-1$ //$NON-NLS-2$
                            URI uri = URI.createURI(classpathEntryElement.getAttribute("path")).resolve( //$NON-NLS-1$
                                    URI.createURI(classpathURL.toString()));
                            IWorkspace workspace = ResourcesPlugin.getWorkspace();
                            IProject project = workspace.getRoot().getProject(javaProject.getProject().getName());
                            if (!project.exists()) {
                                project.create(new NullProgressMonitor());
                            }
                            if (!project.isOpen()) {
                                project.open(new NullProgressMonitor());
                            }
                            IFolder folder = project.getFolder("." + pluginID); //$NON-NLS-1$
                            if (!folder.exists()) {
                                folder.createLink(
                                        new Path(CommonPlugin.asLocalURI(uri).toFileString()).removeTrailingSeparator(),
                                        IResource.ALLOW_MISSING_LOCAL, new NullProgressMonitor());
                            }
                            folder.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
                            IPath path = folder.getFullPath();
                            IClasspathEntry newLibraryEntry = JavaCore.newLibraryEntry(path, null, null, null,
                                    bundle == null ? new IClasspathAttribute[0] : new IClasspathAttribute[] { JavaCore
                                            .newClasspathAttribute(CodeGenUtil.EclipseUtil.PLUGIN_ID_CLASSPATH_ATTRIBUTE_NAME,
                                                    pluginID) }, true);
                            list.add(newLibraryEntry);
                            break;
                        }
                    }
                }
            } catch (Exception exception) {
                ExceptionOperation.operate(exception);
            }
        }
        return list;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaETLProcessor#getCommandLine(java.lang.String, boolean, java.lang.String,
     * java.lang.String)
     */
    public String[] getCommandLine(String targetPlatform, boolean extenalUse, String libPath, String standardJars,
            Set<String> neededLibraries) {
        String classPathSeparator;
        if (targetPlatform == null) {
            classPathSeparator = System.getProperty("path.separator");
        } else {
            if (targetPlatform.equals(EtlProcessScriptsManager.WINDOWS_ENVIRONMENT)) {
                classPathSeparator = ";";
            } else {
                classPathSeparator = ":";
            }
        }
        StringBuffer allLibsPath = new StringBuffer(standardJars);
        for (String string : neededLibraries) {
            allLibsPath.append(libPath + EtlProcessScriptsManager.PATH_SEPARATOR + string
                    + JavaProcessorUtil.TEMP_JAVA_CLASSPATH_SEPARATOR);
        }
        allLibsPath.append(process.getName().toLowerCase() + ".jar");
        String aLibPath = allLibsPath.toString().replaceAll(JavaProcessorUtil.TEMP_JAVA_CLASSPATH_SEPARATOR, classPathSeparator);
        String command = "java"; //$NON-NLS-1$

        IPath classPath = getCompiledCodePath().removeFirstSegments(1);
        String className = classPath.toString().replace('/', '.');

        return new String[] { command, "-Xms256M", "-Xmx1024M", "-cp", aLibPath, className };
    }

    /**
     * Getter for project.
     * 
     * @return the project
     */
    public static IProject getProject() {
        if (project == null) {
            initProject();
        }
        return project;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getInternalPackage".
     * 
     * @return
     * @throws Exception
     */
    public IPackageFragment getInternalPackage() throws Exception {
        IPackageFragment processorPackage = getProjectPackage(JavaProcessorUtil.JAVA_DENGUES_PKG);
        return getProjectPackage(processorPackage, JavaProcessorUtil.JAVA_PROJ_INTERNAL);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.runprocess.IJavaETLProcessor#debug()
     */
    public void debug(final boolean tracEnable) throws CoreException {
        final IPreferenceStore preferenceStore = DebugUITools.getPreferenceStore();

        preferenceStore.setValue(CONSOLE_OPEN_ON_OUT, true);
        preferenceStore.setValue(CONSOLE_OPEN_ON_ERR, true);

        preferenceStore.setValue(IInternalDebugUIConstants.PREF_SWITCH_TO_PERSPECTIVE, MessageDialogWithToggle.ALWAYS);
        preferenceStore.setValue(IInternalDebugUIConstants.PREF_SWITCH_PERSPECTIVE_ON_SUSPEND, MessageDialogWithToggle.ALWAYS);

        IRunnableWithProgress worker = new IRunnableWithProgress() {

            public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                monitor.beginTask("Begin Debug...", IProgressMonitor.UNKNOWN);
                // init class name
                // generateCode(tracEnable);
                IPath classPath = getCompiledCodePath().removeFirstSegments(1);
                String className = classPath.toString().replace('/', '.');
                try {
                    DenguesProcessFactory.debug(getJavaProject(), DenguesProjectFactory.getDenguesProject().getName()
                            .toLowerCase()
                            + classPath.lastSegment().toLowerCase() + " (" + getJavaProject().getElementName() + ")", className //$NON-NLS-1$ //$NON-NLS-2$
                            , getCodeFile());//$NON-NLS-1$ 
                } catch (CoreException e) {
                    e.printStackTrace();
                } finally {
                    monitor.done();
                }
            }

        };
        // preferenceStore.setValue(IDebugPreferenceConstants.CONSOLE_OPEN_ON_OUT, oldValueConsoleOnOut);
        // preferenceStore.setValue(IDebugPreferenceConstants.CONSOLE_OPEN_ON_ERR, oldValueConsoleOnErr);

        IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
        try {
            progressService.runInUI(PlatformUI.getWorkbench().getProgressService(), worker, ResourcesPlugin.getWorkspace()
                    .getRoot());
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
